#include <xpam/com/com.h>

namespace DexterLib
{
    class SampleGrabberCB : public DexterLib::ISampleGrabberCB
    {
    protected:
        int _width, _height;
        xpam::dsp::frame _frame;
        double _time;
    public:
        SampleGrabberCB() : _width(0), _height(0)
        { }

        virtual ~SampleGrabberCB()
        { }

        void frame(xpam::dsp::frame & fr) { fr = _frame; }
        double time() { return _time; }

        // ISampleGrabberCB implementation
        STDMETHOD_(ULONG, AddRef)();
        STDMETHOD_(ULONG, Release)();
        STDMETHOD(QueryInterface)(REFIID riid, void ** ppv);
        STDMETHOD(raw_SampleCB)(double sampleTime, DexterLib::IMediaSample * sample);
        STDMETHOD(raw_BufferCB)(double sampleTime, unsigned char * buffer, long bufferSize);
    };

    STDMETHODIMP_(ULONG) SampleGrabberCB::AddRef() 
    { 
        return 0; 
    }

    STDMETHODIMP_(ULONG) SampleGrabberCB::Release() 
    { 
        return 0; 
    }

    STDMETHODIMP SampleGrabberCB::QueryInterface(REFIID riid, void ** ppv)
    {
        if (riid == DexterLib::IID_ISampleGrabberCB || riid == IID_IUnknown ) 
        {
            *ppv = (void *) static_cast<DexterLib::ISampleGrabberCB *>(this);
            return NOERROR;
        }    

        return E_NOINTERFACE;
    }

    STDMETHODIMP SampleGrabberCB::raw_SampleCB(double sampleTime, DexterLib::IMediaSample * sample)
    {
        unsigned char * buffer = NULL;
        sample->GetPointer(&buffer);
        _frame.assign(buffer, _width, _height, 3);
        _time = sampleTime;
        return S_OK;
    }

    STDMETHODIMP SampleGrabberCB::raw_BufferCB(double sampleTime, unsigned char * buffer, long bufferSize)
    {
        _frame.assign(buffer, _width, _height, 3);
        _time = sampleTime;
        return 0;
    }
}